/**
 * @copyright Copyright (c) 2025 CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author Xie Jinhui
 */

/* 
 * Include application profile management header file
 * This header contains declarations for application profile handling functions
 */
#include "appprofile_manage.h"

/* 
 * Include standard input/output library for file operations
 * Provides functions for file handling and console output
 */
#include <stdio.h>

/* 
 * Include standard library for memory allocation and process control
 * Provides functions for dynamic memory management and program termination
 */
#include <stdlib.h>

/* 
 * Include string manipulation library
 * Provides functions for string operations and memory operations
 */
#include <string.h>

/* 
 * Include system stat library for file status information
 * Provides functions for checking file properties and metadata
 */
#include <sys/stat.h>

/* 
 * Static file pointer for application profile file handling
 * This variable maintains the file stream for the opened profile file
 */
static FILE *out_file = NULL;

/* 
 * Static character buffer for storing application profile content
 * This buffer holds the raw JSON data read from the application profile file
 */
static char *appinfobuff = NULL;

/* 
 * Static cJSON root object for parsed JSON data structure
 * This variable stores the root node of the parsed JSON document
 */
static cJSON *root = NULL;

/**
 * @brief  Read specific key values from application profile JSON structure
 * This internal function extracts values from nested JSON objects based on property and key names
 * 
 * @param  property   Application property category within the JSON structure
 * @param  keyname    Specific key name whose value needs to be retrieved
 * @param  valuebuff  Buffer pointer where the extracted value will be copied
 * @retval Returns number of characters copied on success, -1 on error
 */
static int read_appprofile_json_values(const char *property, const char *keyname, char *valuebuff)
{
    /* 
     * Check if root JSON object is properly initialized
     * Return error if root object is NULL indicating no JSON data loaded
     */
    if (root == NULL) {
        printf("Error: root is NULL\n");
        return -1;  // 空根对象
    }

    /* 
     * Retrieve the property object from root JSON structure
     * This searches for the specified property category in the JSON document
     */
    cJSON *app_obj = cJSON_GetObjectItem(root, property);
    
    /* 
     * Validate that the requested property exists in JSON structure
     * Return error if the specified property category is not found
     */
    if (app_obj == NULL) {
        printf("Error: property '%s' not found\n", property);
        return -1;  // 没有找到指定的 property
    }

    /* 
     * Retrieve the specific key within the property object
     * This searches for the requested key name within the property category
     */
    cJSON *key_obj = cJSON_GetObjectItem(app_obj, keyname);
    
    /* 
     * Validate that the requested key exists within the property
     * Return error if the specified key name is not found
     */
    if (key_obj == NULL) {
        printf("Error: keyname '%s' not found\n", keyname);
        return -1;  // 没有找到指定的 keyname
    }

    /* 
     * Handle string type values from JSON structure
     * Extract and copy string values directly to output buffer
     */
    if (cJSON_IsString(key_obj)) {
        /* 
         * Copy string value from JSON object to output buffer
         * Include null terminator to ensure proper string formatting
         */
        strncpy(valuebuff, key_obj->valuestring, strlen(key_obj->valuestring) + 1);
        
        /* 
         * Return the length of copied string
         * This indicates successful extraction of string value
         */
        return strlen(key_obj->valuestring);  // 返回拷贝的字符数
    } 
    /* 
     * Handle numeric type values from JSON structure
     * Convert numeric values to string representation for output
     */
    else if (cJSON_IsNumber(key_obj)) {
        /* 
         * Convert numeric value to string representation
         * Use safe snprintf to prevent buffer overflow issues
         */
        snprintf(valuebuff, 64, "%d", key_obj->valueint);  // 将数字转换为字符串
        
        /* 
         * Return the length of converted numeric string
         * This indicates successful conversion and extraction
         */
        return strlen(valuebuff);  // 返回拷贝的字符数
    } 
    /* 
     * Handle unsupported JSON value types
     * Return error for types that cannot be processed by this function
     */
    else {
        printf("Error: Unsupported value type for '%s'\n", keyname);
        return -1;  // 不支持的类型
    }
}



/**
 * @brief Open and parse application profile control file
 * This function loads, reads, and parses the application profile JSON file into memory
 * 
 * @param path File system path to the application profile JSON file
 * @retval Returns 0 on success, -1 on failure
 */
int open_appprofile_ctl(const char* path)
{
    //printf("openAppProfile \n");
    
    /* 
     * Open the application profile file in read mode
     * Attempt to access the specified file path for reading
     */
    out_file = fopen(path, "r");
    
    /* 
     * Check if file opening operation was successful
     * Return error if file cannot be opened or accessed
     */
    if (out_file == NULL) {
        perror("open AppProfile error");
        return -1;
    }

    /* 
     * Check if application info buffer already contains data
     * Free existing buffer memory to prevent memory leaks
     */
    if (appinfobuff != NULL) {
        free(appinfobuff);
        appinfobuff = NULL;
    }

    /* 
     * Seek to end of file to determine file size
     * Position file pointer at end to calculate total file length
     */
    if (fseek(out_file, 0, SEEK_END) != 0) {
        printf("Error: fseek failed.\n");
        return -1;
    }

    /* 
     * Get current file position which represents file size
     * Retrieve the total size of the application profile file
     */
    long file_size = ftell(out_file);
    
    /* 
     * Validate that file size retrieval was successful
     * Return error if unable to determine file size
     */
    if (file_size == -1) {
        printf("Error: ftell failed.\n");
        return -1;
    }

    /* 
     * Reset file pointer to beginning of file for reading
     * Reposition to start of file to prepare for content reading
     */
    if (fseek(out_file, 0, SEEK_SET) != 0) {
        printf("Error: fseek failed to reset file pointer.\n");
        return -1;
    }

    /* 
     * Allocate memory buffer for file content storage
     * Create buffer with extra byte for null terminator
     */
    appinfobuff = (char *)malloc(file_size + 1);  // +1 for null terminator
    
    /* 
     * Validate that memory allocation was successful
     * Return error if system cannot allocate required memory
     */
    if (appinfobuff == NULL) {
        printf("Error: Memory allocation failed.\n");
        return -1;
    }

    /* 
     * Read entire file content into memory buffer
     * Load complete file content for JSON parsing
     */
    size_t read_size = fread(appinfobuff, 1, file_size, out_file);
    
    /* 
     * Verify that complete file content was read
     * Return error if read operation was incomplete
     */
    if (read_size != file_size) {
        printf("Error: Failed to read the expected number of bytes.\n");
        free(appinfobuff);  // 读取失败时释放已分配的内存
        appinfobuff = NULL;
        return -1;
    }

    /* 
     * Add null terminator to create proper C string
     * Ensure buffer content is properly terminated for string operations
     */
    appinfobuff[read_size] = '\0';

    /* 
     * Clear existing root JSON object if present
     * Remove previous JSON data to prepare for new parsing
     */
        //先清空root节点
    if(NULL != root)
    {
        cJSON_Delete(root);
        root = NULL;
    }
    
    /* 
     * Parse JSON content from file buffer into cJSON structure
     * Convert raw JSON text into structured data representation
     */
    root = cJSON_Parse(appinfobuff);
    
    /* 
     * Validate that JSON parsing was successful
     * Return error if JSON content is malformed or invalid
     */
    if (root == NULL) {
        printf("Error: Failed to parse JSON\n");
        free(appinfobuff);
        appinfobuff = NULL;
        return -1;
    }

    /* 
     * Free temporary file content buffer after successful parsing
     * Release memory since JSON data is now in structured form
     */
    free(appinfobuff);
    appinfobuff = NULL;
    
    /* 
     * Return success indication
     * Application profile is now loaded and ready for use
     */
    return 0;  // 成功
}

/**
 * @brief Close application profile control and cleanup resources
 * This function releases all allocated resources and closes file handles
 * 
 * @retval Always returns 0 indicating successful cleanup
 */
int close_appprofile_ctl(void)
{
    /* 
     * Check if root JSON object exists and needs cleanup
     * Delete JSON structure to free allocated memory
     */
    //如果 root 已经分配，释放
    if(NULL != root)
    {
        cJSON_Delete(root);
        root = NULL;
    }

    /* 
     * Check if application info buffer exists and needs cleanup
     * Free buffer memory to prevent memory leaks
     */
    // 如果 appinfobuff 已经分配，释放
    if (NULL != appinfobuff) {
        free(appinfobuff);
        appinfobuff = NULL;
    }

    /* 
     * Check if file handle exists and needs cleanup
     * Close file stream to release system resources
     */
    // 如果 out_file 已经分配，释放
    if(NULL != out_file)
    {
        fclose(out_file);
    }

    /* 
     * Return success indication
     * All resources have been properly released
     */
    return 0;  // 成功
}

/**
 * @brief Public interface to get application profile information
 * This function provides external access to application profile data through property and key names
 * 
 * @param  property   Application property category within JSON structure
 * @param  keyname    Specific key name whose value needs to be retrieved
 * @param  valuebuff  Output buffer where extracted value will be stored
 * @retval Returns 0 on success, -1 on error
 */
int getAppProfileInfo(const char *property, const char *keyname, char *valuebuff)
{
    /* 
     * Call internal function to read JSON values
     * Delegate actual JSON processing to internal implementation
     */
    int ret = read_appprofile_json_values(property,keyname,valuebuff);
    
    /* 
     * Check if value retrieval was successful
     * Return success if positive character count was returned
     */
    if(0 <= ret)
    {
        return 0;
    }
    
    /* 
     * Return error indication
     * Value retrieval failed due to missing data or parsing error
     */
    return -1;
}

/* 
 * Get the root node of application profile JSON structure
 * This function provides access to the complete parsed JSON structure
 * 
 * @return Pointer to root cJSON object, NULL if not initialized
 */
cJSON * get_app_profile_root(void){
    /* 
     * Return root JSON object pointer
     * Provides direct access to parsed JSON structure for advanced operations
     */
    return root;
}